package com.xiaotu.spider.project.pageprocessor.nettv;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import com.xiaotu.common.model.NetTVModel;
import com.xiaotu.common.util.Constants;
import com.xiaotu.common.util.DateUtils;
import com.xiaotu.common.util.HtmlUtil;
import com.xiaotu.common.util.HttpUtils;
import com.xiaotu.common.util.PageUtils;
import com.xiaotu.common.util.RegexUtils;
import com.xiaotu.common.util.SepratorUtil;
import com.xiaotu.common.util.StringUtil;
import com.xiaotu.spider.AUrlPageProcessor;

import net.sf.json.JSONObject;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.selector.Html;

/**
 * 优酷最新二年网剧爬取：名称、集数、类型、导演、主演、语言、年份、简介、播放量、评分
 *
 * @auther 王艳龙
 * @create 2017/10/13
 */
@Component("YOUKUNetTVPageProcessor")
public class YOUKUNetTVPageProcessor extends AUrlPageProcessor
{
    //网剧列表的页面地址，"%s"为要替换的年份
    private static final String BASE_URL =
    		"http://list.youku.com/category/show/c_97_r_%s_s_1_d_1.html?spm=a2h1n.8251845.filterPanel.5!4~1~3!2~A";

    //数据范围，只需要爬取这二年的网剧，该变量将被逐个拼到url中
    private static final String[] YEARS = DateUtils.getRecentYears(3);

    /**
     * 页面内容被爬虫框架捕获后，将回调此方法，来完成页面数据的解析
     *
     * @param page
     */
    @Override
    public void process(Page page)
    {
        if (Constants.PageDataType.SEARCH_LIST.equals(this.getPageDataType(page))){//列表页面处理
        	this.listProcess(page);
        	this.addNextPage(page);
        }else if(Constants.PageDataType.TV_COMMENT.equals(this.getPageDataType(page))){//播放节目简介处理
        	this.baseInfos(page);
        }else{
        	page.putField(NetTVModel.class.getName(), detailProcess(page));//详情页面处理
        }
    }
    
    /**
     * 常规详情页面解析
     *
     * @param page
     */
    private NetTVModel detailProcess(Page page)
    {
        Map<String, Object> tvMap = page.getRequest().getExtras();
        String htmlStr =page.getHtml().xpath("//div[@class='p-base']/ul").toString();
        Html divList = new Html(htmlStr);
        String title = HtmlUtil.delHTMLTag(divList.xpath("//ul/li[@class='p-row p-title']/text()").get().replace("：", ""));
		String sets = divList.xpath("//ul/li[@class='p-row p-renew']/text()").regex(RegexUtils
                .REGEX_INTEGER).get();
		String score = divList.xpath("//ul/li[@class='p-score']/span[@class='star-num']/text()").get();
		String desc = HtmlUtil.delHTMLTag(divList.xpath("//ul/li[@class='p-row p-intro']/span[@class='text']/text()").get());
		String actor =  this.getFormateFigure(HtmlUtil.delHTMLTag(divList.xpath("//ul/li[@class='p-performer']").get().replaceAll("主演：", "")));
		
		String director="";
		String area="";
		String type="";
		String play="";
		String playYear ="";
		String typeValue =divList.xpath("//ul/li[8]").get();
		if(StringUtils.isNotEmpty(typeValue) && typeValue.contains("地区：")){
			director = this.getFormateFigure(divList.xpath("//ul/li[7]/a/text()").get());
			area = divList.xpath("//ul/li[8]/a/text()").get();
			type = this.getFormateFigure(HtmlUtil.delHTMLTag(divList.xpath("//ul/li[9]").get().replace("类型：", "")));
			play = divList.xpath("//ul/li[10]/text()").get().replace("总播放数：", "");
			playYear = HtmlUtil.delHTMLTag(divList.xpath("//ul/li[@class='p-row p-title']/span[@class='sub-title']/text()").get());
		}else{
			director = this.getFormateFigure(divList.xpath("//ul/li[8]/a/text()").get());
			area = divList.xpath("//ul/li[9]/a/text()").get();
			type = this.getFormateFigure(HtmlUtil.delHTMLTag(divList.xpath("//ul/li[10]").get().replace("类型：", "")));
			play = divList.xpath("//ul/li[11]/text()").get().replace("总播放数：", "");
			playYear = HtmlUtil.delHTMLTag(divList.xpath("//ul/li/span[@class='pub']/text()").get());
		}
    	
		return new NetTVModel(Constants.TargetType.OTHER_TYPE_ID, title, Constants.SiteName
    			.YOUKU, sets, type, null, area, playYear, director, actor, desc, play, score,StringUtil.nullToString(tvMap.get("year")));
        	
    }
    
    private String getFormateFigure(String figure)
    {
        if (StringUtils.isEmpty(figure))
            return StringUtils.EMPTY;
        return figure.replaceAll(" /  ", SepratorUtil.SEP_COMMA_EN).replaceAll("/ ", SepratorUtil
                .SEP_COMMA_EN).replaceAll("/", SepratorUtil.SEP_COMMA_EN).trim();
    }

    /**
     * 将列表中的所有网剧添加到爬取池中
     *
     * @param page
     */
    private void listProcess(Page page)
    {
        List<String> list = page.getHtml().xpath("//div[@class='box-series']//ul//li").all();
        list.forEach(divStr -> PageUtils.addTargetRequest(page, new Html(divStr).xpath
                ("//div[@class='yk-pack pack-film']//div[@class='p-thumb']/a/@href").get(), page.getRequest().getExtras()));
    }
    
    /**
     * 将下一页网剧列表页面放入爬取池中
     *
     * @param page
     */
    private void addNextPage(Page page)
    {
        String href = page.getHtml().xpath("//div[@class='yk-pager']/ul/li[@class='next']/a/@href")
                .get();
        if (StringUtils.isNotEmpty(href))
            PageUtils.addTargetRequest(page, href, page.getRequest().getExtras());

    }
    
    /**
     * 将播放简介地址放入爬取池中
     *
     * @param page
     */
    private void baseInfos(Page page)
    {
        String link = page.getHtml().xpath("//div[@class='base_info']/a[@class='desc-link']/@href")
                .get();
        if (StringUtils.isNotEmpty(link))
            PageUtils.addTargetRequest(page, link, page.getRequest().getExtras());

    }
    
    /**
     * 获取网剧播放量
     *
     * @param html
     * @return
     */
    private String getPlayCount(String playlistId)
    {
        String url ="http://count.vrs.sohu.com/count/query_Album.action?"
        		+ "albumId="+playlistId+""
        		+ "&jsonp=counttopInfo&type=2";
        String data = HttpUtils.httpGetJSONP(url);
        if (StringUtils.isEmpty(data))
            return StringUtils.EMPTY;
        String playCount = RegexUtils.regexSearch("counttopInfo=" + RegexUtils.REGEX_NUMBER, data);
        if (StringUtils.isEmpty(playCount))
            return StringUtils.EMPTY;
        return RegexUtils.regexSearch(RegexUtils.REGEX_NUMBER, playCount);
    }
    
    /**
     * 获取网剧评分
     *
     * @param html
     * @return
     */
    private String getScore(String playlistId)
    {
        String url ="http://vote.biz.itc.cn/query/score.json?callback=jQuery172010347057230044143_1507883239551"
        		+ "&albumId="+playlistId+""
        		+ "&_=1507883239750";
        System.out.println(url);
        String data = HttpUtils.httpGetJSONP(url);
        if (StringUtils.isEmpty(data))
            return StringUtils.EMPTY;
        String score = getSrings(data, Pattern.quote("\"score\":\"") +
                "(.*?)" + Pattern.quote("\","));
        if (StringUtils.isEmpty(score))
            return StringUtils.EMPTY;
        return RegexUtils.regexSearch(RegexUtils.REGEX_NUMBER, score);
    }

    /**
     * 初始化要爬取的地址，本程序中为二个地址（对应二个年份）
     *
     * @return
     */
    @Override
    protected List<JSONObject> getStartRequestUrlsAndParams()
    {
        List<JSONObject> list = new ArrayList<>();
        Stream.of(YEARS).forEach(year ->
        {
            JSONObject target = new JSONObject();
            target.put("year", year);
            target.put(URL_KEY, String.format(BASE_URL, year));
            list.add(target);
        });
        return list;
    }
    
    /**
     * 获取多个目标字符串
     */
    public static String getSrings(String input, String regex)
    {
    	String result=null;
        Pattern pat = Pattern.compile(regex, Pattern.DOTALL);
        Matcher mat = pat.matcher(input);
        while (mat.find())
        {
            result = mat.group(1);
        }
        return result;
    }

    /**
     * 爬取链接为静态地址时，该方法返回空，固定写法
     *
     * @return
     */
    @Override
    protected String[] getStartRequestUrls()
    {
        return null;
    }

    /**
     * 爬取任务的标识
     *
     * @return
     */
    @Override
    protected String getSpiderType()
    {
        return "YOUKU_NETTV";
    }

    /**
     * 返回本页面的数据类型
     *
     * @param page 爬取页面
     * @return
     */
    @Override
    public String getPageDataType(Page page)
    {
        if (page.getUrl().toString().contains("list.youku.com/category")){//网剧列表页面
        	return Constants.PageDataType.SEARCH_LIST;
        }else if (page.getUrl().toString().contains("v_show")){//网剧播放页面
        	return Constants.PageDataType.TV_COMMENT;
        }else{
        	return Constants.PageDataType.TV_RECORD;//网剧详情页面
        }
    }
}
